<!doctype html>



  


<html class="theme-next mist use-motion" lang="zh-Hans">
<head>
  <meta charset="UTF-8"/>
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1"/>



<meta http-equiv="Cache-Control" content="no-transform" />
<meta http-equiv="Cache-Control" content="no-siteapp" />















  
  
  <link href="/lib/fancybox/source/jquery.fancybox.css?v=2.1.5" rel="stylesheet" type="text/css" />




  
  
  
  

  
    
    
  

  
    
      
    

    
  

  

  
    
      
    

    
  

  
    
      
    

    
  

  
    
    
    <link href="//fonts.googleapis.com/css?family=Microsoft YaHei:300,300italic,400,400italic,700,700italic|Georgia:300,300italic,400,400italic,700,700italic|Lobster Two:300,300italic,400,400italic,700,700italic|consolas:300,300italic,400,400italic,700,700italic&subset=latin,latin-ext" rel="stylesheet" type="text/css">
  






<link href="/lib/font-awesome/css/font-awesome.min.css?v=4.6.2" rel="stylesheet" type="text/css" />

<link href="/css/main.css?v=5.1.0" rel="stylesheet" type="text/css" />


  <meta name="keywords" content="Devstack,Openstack,开发环境," />





  <link rel="alternate" href="/atom.xml" title="一本正经的小马" type="application/atom+xml" />




  <link rel="shortcut icon" type="image/x-icon" href="/images/favicon1.ico?v=5.1.0" />






<meta name="description" content="Devstack 是面向 Openstack 开发者的快速自动化部署 Bash 脚本，提供了辅助开发和调试的源码环境，能够支持 All-In-One 和多节点部署模式，同时也支持 Plug-in 模式。Devstack 的使用可以说贯穿整个 Openstack 开发生涯，熟练的使用 Devstack 能有效提高开发效率。">
<meta name="keywords" content="Devstack,Openstack,开发环境">
<meta property="og:type" content="article">
<meta property="og:title" content="Devstack部署Openstack开发环境">
<meta property="og:url" content="https://www.hanbert.cn/2017/04/09/Devstack部署Openstack开发环境/index.html">
<meta property="og:site_name" content="一本正经的小马">
<meta property="og:description" content="Devstack 是面向 Openstack 开发者的快速自动化部署 Bash 脚本，提供了辅助开发和调试的源码环境，能够支持 All-In-One 和多节点部署模式，同时也支持 Plug-in 模式。Devstack 的使用可以说贯穿整个 Openstack 开发生涯，熟练的使用 Devstack 能有效提高开发效率。">
<meta property="og:locale" content="zh-Hans">
<meta property="og:image" content="http://img.blog.csdn.net/20170114134811369?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvSm1pbGs=/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/SouthEast">
<meta property="og:updated_time" content="2017-10-02T17:47:28.682Z">
<meta name="twitter:card" content="summary">
<meta name="twitter:title" content="Devstack部署Openstack开发环境">
<meta name="twitter:description" content="Devstack 是面向 Openstack 开发者的快速自动化部署 Bash 脚本，提供了辅助开发和调试的源码环境，能够支持 All-In-One 和多节点部署模式，同时也支持 Plug-in 模式。Devstack 的使用可以说贯穿整个 Openstack 开发生涯，熟练的使用 Devstack 能有效提高开发效率。">
<meta name="twitter:image" content="http://img.blog.csdn.net/20170114134811369?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvSm1pbGs=/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/SouthEast">



<script type="text/javascript" id="hexo.configurations">
  var NexT = window.NexT || {};
  var CONFIG = {
    root: '/',
    scheme: 'Mist',
    sidebar: {"position":"left","display":"post","offset":12,"offset_float":0,"b2t":false,"scrollpercent":false},
    fancybox: true,
    motion: true,
    duoshuo: {
      userId: '0',
      author: '博主'
    },
    algolia: {
      applicationID: '',
      apiKey: '',
      indexName: '',
      hits: {"per_page":10},
      labels: {"input_placeholder":"Search for Posts","hits_empty":"We didn't find any results for the search: ${query}","hits_stats":"${hits} results found in ${time} ms"}
    }
  };
</script>



  <link rel="canonical" href="https://www.hanbert.cn/2017/04/09/Devstack部署Openstack开发环境/"/>





  <title> Devstack部署Openstack开发环境 | 一本正经的小马 </title>
</head>

<body itemscope itemtype="http://schema.org/WebPage" lang="zh-Hans">

  







  <script type="text/javascript">
    (function() {
      var hm = document.createElement("script");
      hm.src = "//tajs.qq.com/stats?sId=61405345";
      var s = document.getElementsByTagName("script")[0];
      s.parentNode.insertBefore(hm, s);
    })();
  </script>








  
  
    
  

  <div class="container sidebar-position-left page-post-detail ">
    <div class="headband"></div>

    <header id="header" class="header" itemscope itemtype="http://schema.org/WPHeader">
      <div class="header-inner"><div class="site-brand-wrapper">
  <div class="site-meta ">
    

    <div class="custom-logo-site-title">
      <a href="/"  class="brand" rel="start">
        <span class="logo-line-before"><i></i></span>
        <span class="site-title">一本正经的小马</span>
        <span class="logo-line-after"><i></i></span>
      </a>
    </div>
      
        <p class="site-subtitle">假装不正经</p>
      
  </div>

  <div class="site-nav-toggle">
    <button>
      <span class="btn-bar"></span>
      <span class="btn-bar"></span>
      <span class="btn-bar"></span>
    </button>
  </div>
</div>

<nav class="site-nav">
  

  
    <ul id="menu" class="menu">
      
        
        <li class="menu-item menu-item-home">
          <a href="/" rel="section">
            
              <i class="menu-item-icon fa fa-fw fa-home"></i> <br />
            
            首页
          </a>
        </li>
      
        
        <li class="menu-item menu-item-essay">
          <a href="/categories/随笔" rel="section">
            
              <i class="menu-item-icon fa fa-fw fa-book"></i> <br />
            
            随笔
          </a>
        </li>
      
        
        <li class="menu-item menu-item-study">
          <a href="/categories/学习" rel="section">
            
              <i class="menu-item-icon fa fa-fw fa-paper-plane"></i> <br />
            
            学习
          </a>
        </li>
      
        
        <li class="menu-item menu-item-other">
          <a href="/categories/杂记" rel="section">
            
              <i class="menu-item-icon fa fa-fw fa-list"></i> <br />
            
            杂记
          </a>
        </li>
      
        
        <li class="menu-item menu-item-about">
          <a href="/about" rel="section">
            
              <i class="menu-item-icon fa fa-fw fa-user"></i> <br />
            
            关于
          </a>
        </li>
      

      
        <li class="menu-item menu-item-search">
          
            <a href="javascript:;" class="popup-trigger">
          
            
              <i class="menu-item-icon fa fa-search fa-fw"></i> <br />
            
            搜索
          </a>
        </li>
      
    </ul>
  

  
    <div class="site-search">
      
  <div class="popup search-popup local-search-popup">
  <div class="local-search-header clearfix">
    <span class="search-icon">
      <i class="fa fa-search"></i>
    </span>
    <span class="popup-btn-close">
      <i class="fa fa-times-circle"></i>
    </span>
    <div class="local-search-input-wrapper">
      <input autocapitalize="off" autocomplete="off" autocorrect="off"
             placeholder="搜索..." spellcheck="false"
             type="text" id="local-search-input">
    </div>
  </div>
  <div id="local-search-result"></div>
</div>



    </div>
  
</nav>



 </div>
    </header>

    <main id="main" class="main">
      <div class="main-inner">
        <div class="content-wrap">
          <div id="content" class="content">
            

  <div id="posts" class="posts-expand">
    

  

  
  
  

  <article class="post post-type-normal " itemscope itemtype="http://schema.org/Article">
    <link itemprop="mainEntityOfPage" href="https://www.hanbert.cn/2017/04/09/Devstack部署Openstack开发环境/">

    <span hidden itemprop="author" itemscope itemtype="http://schema.org/Person">
      <meta itemprop="name" content="小马">
      <meta itemprop="description" content="">
      <meta itemprop="image" content="/images/avatar1.jpg">
    </span>

    <span hidden itemprop="publisher" itemscope itemtype="http://schema.org/Organization">
      <meta itemprop="name" content="一本正经的小马">
    </span>

    
      <header class="post-header">

        
        
          <h1 class="post-title" itemprop="name headline">
            
            
              
                Devstack部署Openstack开发环境
              
            
          </h1>
        

        <div class="post-meta">
          <span class="post-time">
            
              <span class="post-meta-item-icon">
                <i class="fa fa-calendar-o"></i>
              </span>
              
                <span class="post-meta-item-text">发表于</span>
              
              <time title="创建于" itemprop="dateCreated datePublished" datetime="2017-04-09T20:01:19+08:00">
                2017-04-09
              </time>
            

            

            
          </span>

          
            <span class="post-category" >
            
              <span class="post-meta-divider">|</span>
            
              <span class="post-meta-item-icon">
                <i class="fa fa-folder-o"></i>
              </span>
              
                <span class="post-meta-item-text">分类于</span>
              
              
                <span itemprop="about" itemscope itemtype="http://schema.org/Thing">
                  <a href="/categories/学习/" itemprop="url" rel="index">
                    <span itemprop="name">学习</span>
                  </a>
                </span>

                
                
              
            </span>
          

          
            
              <span class="post-comments-count">
                <span class="post-meta-divider">|</span>
                <span class="post-meta-item-icon">
                  <i class="fa fa-comment-o"></i>
                </span>
                <a class="cloud-tie-join-count" href="/2017/04/09/Devstack部署Openstack开发环境/#comments" itemprop="discussionUrl">
                  <span class="post-comments-count join-count" itemprop="commentCount"></span>
                </a>
              </span>
            
          

          
          
             <span id="/2017/04/09/Devstack部署Openstack开发环境/" class="leancloud_visitors" data-flag-title="Devstack部署Openstack开发环境">
               <span class="post-meta-divider">|</span>
               <span class="post-meta-item-icon">
                 <i class="fa fa-eye"></i>
               </span>
               
                 <span class="post-meta-item-text">阅读次数 </span>
               
                 <span class="leancloud-visitors-count"></span>
             </span>
          

          

          

          

        </div>
      </header>
    


    <div class="post-body" itemprop="articleBody">

      
      

      
        <p>Devstack 是面向 Openstack 开发者的快速自动化部署 Bash 脚本，提供了辅助开发和调试的源码环境，能够支持 All-In-One 和多节点部署模式，同时也支持 Plug-in 模式。Devstack 的使用可以说贯穿整个 Openstack 开发生涯，熟练的使用 Devstack 能有效提高开发效率。 </p>
<a id="more"></a>
<blockquote>
<p>正如官方所强调的：Devstack不适合生产环境！</p>
</blockquote>
<h3 id="支持的服务"><a href="#支持的服务" class="headerlink" title="支持的服务"></a>支持的服务</h3><p><strong>基础的操作系统</strong></p>
<p>OpenStack技术委员会把现在的CI策略定义为支持最新的Ubuntu发行版和最新的RHEL发行版（为了测试Python2.6）。</p>
<ul>
<li><strong>Ubuntu</strong>: current 长期支持版(LTS release)加上现在的开发版</li>
<li><strong>Fedora</strong>: 当前版本加上之前的版本</li>
<li><strong>RHEL</strong>: 当前的主要发行版本</li>
<li>其他OS平台可能继续支持，比如：<strong>Debian</strong>、<strong>OpenSUSE</strong>，但不是所有这些存在的平台都能得到支持</li>
<li>Ubuntu或是Fedora的补丁不会被支持，因为对其他的平台有副作用</li>
</ul>
<p><strong>数据库</strong></p>
<ul>
<li>MySQL</li>
<li>PostgreSQL</li>
</ul>
<p><strong>消息队列</strong></p>
<ul>
<li>Rabbit</li>
<li>Qpid</li>
</ul>
<p><strong>Web服务器</strong></p>
<ul>
<li>Apache</li>
</ul>
<p><strong>Openstack网络</strong></p>
<p>默认使用Nova Network，可以选定使用<code>Neutron</code></p>
<ul>
<li><strong>Nova Network</strong>: FlatDHCP</li>
<li><strong>Neutron</strong>: 使用<code>linuxbridge</code>或是 <code>OpenVSwitch</code>的基本配置，接近于初始的<code>FlatDHCP</code>方式。</li>
</ul>
<p><strong>Openstack服务</strong></p>
<p>DevStack中配置的默认服务有：</p>
<ul>
<li>认证（Keystone）</li>
<li>对象存储（Swift）</li>
<li>映像存储（Glance）</li>
<li>块存储（Cinder）</li>
<li>计算（Nova）</li>
<li>控制面板（Horizon）</li>
<li>编排（Heat）</li>
</ul>
<blockquote>
<p>其他没有直接包含在DevStack中的附加服务可以通过插件机制绑定在<code>stack.sh</code>里面<br>插件机制可以调用脚本来进行配置和启动相关服务</p>
</blockquote>
<p><strong>节点配置</strong></p>
<ul>
<li>单一节点</li>
<li>多节点，但不是重点支持对象，核心团队并不定期测试多节点的配置，即使测试也只包含最小配置</li>
</ul>
<h3 id="Devstack-的安装与使用"><a href="#Devstack-的安装与使用" class="headerlink" title="Devstack 的安装与使用"></a>Devstack 的安装与使用</h3><p>Devstack的安装过程比较简单，只需要从github库中git clone下来源码到本地，然后对本地做简单的配置即可。</p>
<p><strong>安装Linux</strong><br>本次使用的是Openstack官网推荐的<code>Ubuntu16.04</code>。<br>由于Devstack自动部署过程中很多地方都需要用到<code>git</code>的相关命令，所以我们先为操作系统安装<code>git</code>：<br><figure class="highlight plain"><table><tr><td class="gutter"><pre><div class="line">1</div></pre></td><td class="code"><pre><div class="line"># apt-get install git</div></pre></td></tr></table></figure></p>
<p><strong>添加<code>stack</code>用户</strong><br>Devstack必须运行在非<code>root</code>用户下，且该用户必须要<code>sudo</code>权限，本次为系统添加一个<code>stack</code>用户。<br><figure class="highlight plain"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div></pre></td><td class="code"><pre><div class="line">#切换到root用户</div><div class="line">$ su</div><div class="line">#添加账户，并指定shell和home所在地</div><div class="line"># useradd -s /bin/bash/ -d /opt/stack -m stack</div></pre></td></tr></table></figure></p>
<p>为刚添加的<code>stack</code>账户添加<code>sudo</code>权限<br><figure class="highlight plain"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div></pre></td><td class="code"><pre><div class="line"># tee &lt;&lt;&lt; &quot;stack ALL=(ALL) NOPASSWD:ALL&quot; /etc/sudoers</div><div class="line"># su - stack</div></pre></td></tr></table></figure></p>
<blockquote>
<p>在Ubuntu中<code>sudoers</code>即使<code>root</code>用户默认也没有权限修改的，所以使用<code>tee</code>命令来写入，可以避免权限问题<br>也可以直接找到<code>/etc/shudoers</code>这个文件，改变其读写权限，然后打开文件写入，当不推荐这样做 </p>
</blockquote>
<p><strong>下载Devstack</strong></p>
<p>可以直接从github上下载最新版的额Devstack源码<br><figure class="highlight plain"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div></pre></td><td class="code"><pre><div class="line">$ git clone https://git.openstack.org/openstack-dev/devstack</div><div class="line">$ cd devstack</div></pre></td></tr></table></figure></p>
<p>Download 下来的源码中就包含安装Openstack的脚本和相应的配置模板，理论上，现在就可以运行<code>stack.sh</code>脚本来安装Openstack。但往往为了方便我们开发使用，及保证安装的成功率，我们会在<code>local.conf</code>文件中进行一些配置，覆盖掉其默认的配置后，再进行安装。</p>
<p><strong>开始安装</strong></p>
<p>下载完Devstack，并做好配置后，就可以开始安装Openstack了，只需要运行<code>devstack/</code>目录下的<code>stack.sh</code>脚本既可以全自动进行安装，这期间会遇到一些问题，需要一点点手动解决。所以安装时间的长短因人而异。<br><figure class="highlight plain"><table><tr><td class="gutter"><pre><div class="line">1</div></pre></td><td class="code"><pre><div class="line">$ ./stack.sh</div></pre></td></tr></table></figure></p>
<p>由于默认Devstack是从github直接拉取源码进行安装，所以需要一个好的网络环境才可以，如果不具备，则可以考虑换一个靠谱点的<code>git</code>库，比如：<code>http://git.trystack.cn</code>，这个git库测试性能良好。如果一切顺利的话，大概20-30分钟可以完全部署完。如果遇到错误，需要手动解决ERROR后重新跑脚本，这样安装时间可能是具体情况无限制的延长。</p>
<h3 id="Devstack的配置过程"><a href="#Devstack的配置过程" class="headerlink" title="Devstack的配置过程"></a>Devstack的配置过程</h3><p>Devstack一致致力于通过最少的配置完成最多的功能。因为各个项目加入了新的特性，新的项目加入，还有不同的组合需要测试，选项的数目已经飞速地膨胀了。DevStack的传统做法是从<code>localrc</code>文件得到所有的本地化的配置和定制信息。传递给各个项目的配置变量的数目也在增加。原有的机制 (EXTRAS_OPTS之类)需要对每个文件进行编码，已经不太适应现在的环境。<br>在2013年10月引入了一个新的配置方式<code>local.conf</code>（参看<a href="https://review.openstack.org/#/c/46768/），希望能够简化配置过程，达到下列目的：" target="_blank" rel="external">https://review.openstack.org/#/c/46768/），希望能够简化配置过程，达到下列目的：</a></p>
<ul>
<li>在单一的文件中包含所有非默认的本地配置</li>
<li>与 localrc 的方式向后兼容，保证迁移过程的平滑</li>
<li>允许对任意配置文件中的设置进行更改</li>
</ul>
<blockquote>
<p>现在 Devstack 提供了两种配置安装的方式 local.conf(新版) 和 localrc(旧版),，两种方式我们都应该有所了解， 因为在不同的团队中会习惯的选择使用其中一种甚至两种方式。</p>
</blockquote>
<p><strong>local.conf</strong></p>
<p><code>local.conf</code>文件的样例路径为：<code>devstack/samples/local.conf</code></p>
<p>新的配置文件是<code>local.conf</code>，和旧的<code>localrc</code>文件在同一个目录。它是一个修正后的<code>INI</code>格式文件，引入了<code>meta-section</code>（<code>[[&lt;phase&gt;|&lt;config-file-name&gt;]]</code>）来承载额外的信息。改文件最终会被<code>stack.sh</code>脚本加载使用，所以其语法必须是符合<code>Bash</code>语法规则的，比如：等号“<code>=</code>”的两边不能存在空格。</p>
<p><code>Section</code>（也就是<code>&lt;phase&gt;</code>）有以下几种类型：”local”、”post-config”、”extra”、”post-extra”。它们规定了Devstack的安装流程和配置，在安装过程中会严格按照这个顺序进行读取和执行：</p>
<ol>
<li><strong>local</strong>：对应的Section为<code>[[local|localrc]]</code>，指定在<code>local.conf</code>被<code>stackrc</code>加载之前，先从<code>localrc</code>中提取配置项，配置实例如下：</li>
</ol>
<figure class="highlight bash"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div></pre></td><td class="code"><pre><div class="line">[[<span class="built_in">local</span>|localrc]]</div><div class="line">ADMIN_PASSWORD=nomoresecret</div><div class="line">DATABASE_PASSWORD=stackdb</div><div class="line">RABBIT_PASSWORD=stackqueue</div><div class="line">SERVICE_PASSWORD=<span class="variable">$ADMIN_PASSWORD</span></div></pre></td></tr></table></figure>
<ol>
<li><strong>post-config</strong>：对应的Section为<code>[[post-config|/$Q_PLUGIN_CONF_FILE]]</code>，指定在项目服务自动配置完成后，且在服务正式启动之前，这其中的配置选项会被执行，配置实例如下：</li>
</ol>
<figure class="highlight bash"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div><div class="line">9</div></pre></td><td class="code"><pre><div class="line">[[post-config|/<span class="variable">$NOVA_CONF</span>]]</div><div class="line"></div><div class="line">[DEFAULT]</div><div class="line">use_syslog = True</div><div class="line"></div><div class="line">[osapi_v3]</div><div class="line">enabled = False</div><div class="line"></div><div class="line"><span class="comment"># <span class="doctag">NOTE:</span> Q_PLUGIN_CONF_FILE 独特之处在于它的配置项如果在前面不加 `/`， 那么这个配置项就不会生效。所以为了使其生效添加 `/` 是必须的。</span></div></pre></td></tr></table></figure>
<ol>
<li><strong>extra</strong>：指定在各Openstack项目的主服务启动之后，并且在<code>extra.d</code>中的文件别执行之前，<code>extra</code>的配置项会被执行</li>
<li><strong>post-extra</strong>：指定在<code>extra.d</code>中的文件被执行之后，执行<code>post-extra</code>中的配置项。</li>
</ol>
<blockquote>
<p>从以上可以看出，这么多的Section只是指定了其中的配置项在安装过程中的那个阶段被加载，一般情况下，我们只需要关注<code>local</code>这个Section即可，其他的稍作了解一下即可。</p>
</blockquote>
<p><code>[[local|localrc]]</code>是一个非常特别的Section，我们可以将配置项全部都定义到其下，并且它还指定了是否会将Devstack根目录下的<code>localrc</code>文件的配置项提取到其下，同时也允许所有的自定义安装配置项都包含在<code>localrc</code>文件中。</p>
<blockquote>
<p>这样做只是为了将Devstack的配置方式从<code>localrc</code>平滑过渡到<code>local.conf</code>，也就是说，可以将所有的安装配置项都定义到<code>localrc</code>，而无需修改<code>local.conf</code>文件。</p>
</blockquote>
<p><strong>一个最小化安装Openstack的<code>local.conf</code>配置样例</strong>：</p>
<figure class="highlight bash"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div></pre></td><td class="code"><pre><div class="line">[[<span class="built_in">local</span>|localrc]]</div><div class="line">HOST_IP=192.168.0.2 </div><div class="line">ADMIN_PASSWORD=&lt;YOUR_PASSWORD&gt;</div><div class="line">DATABASE_PASSWORD=<span class="variable">$ADMIN_PASSWORD</span></div><div class="line">RABBIT_PASSWORD=<span class="variable">$ADMIN_PASSWORD</span></div><div class="line">SERVICE_PASSWORD=<span class="variable">$ADMIN_PASSWORD</span></div><div class="line"><span class="comment">#FIXED_RANGE=172.31.1.0/24</span></div><div class="line"><span class="comment">#FLOATING_RANGE=192.168.20.0/25</span></div></pre></td></tr></table></figure>
<p>在上面的配置中，主要做了两件事情，第一、在<code>HOST_IP</code>字段指定本机的IP，这个是为了方面后面建立Endpoint，即所有服务的API用到的IP。理论上，Devstack可以自动检测本机IP，但是这个功能不能特别完善，有时候会出错，所有建议手动指定；第二、指定了各项需要服务的密码，<code>&lt;YOUR_PASSWORD&gt;</code>字段换成你自己想用的密码即可。<br><code>FIXED_RANGE</code>和<code>FLOATING_RANGE</code>两个字段可以用来指定内网和公网IP地址的范围，此处被注释掉了，使用其默认的网络配置。</p>
<h3 id="Devstack的部署流程及需要注意的问题"><a href="#Devstack的部署流程及需要注意的问题" class="headerlink" title="Devstack的部署流程及需要注意的问题"></a>Devstack的部署流程及需要注意的问题</h3><p>Devstack的自动化部署流程大概包含以下几个主要步骤：</p>
<ul>
<li>加载配置文件<code>local.conf</code>和<code>localrc</code>(如果用到了的话)</li>
<li>安装依赖包，此时是从系统的软件库中拉取的依赖包，包括安装<code>pip</code>的过程</li>
<li>安装消息队列和数据库</li>
<li>安装Openstack Clients</li>
<li>安装并配置Openstack的各项服务，此时为从github库中直接拉取源码</li>
<li>下载和上传镜像文件，从镜像的提供方官网下载的镜像</li>
<li>显示登录信息，出现这个信息说明部署成功了</li>
</ul>
<p><img src="http://img.blog.csdn.net/20170114134811369?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvSm1pbGs=/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/SouthEast" alt="@自动化部署的流程"></p>
<p>其中下载依赖包，由于是从系统的软件库中直接边下载变安装的，所以建议提前对操作系统进行换源，以防以为网络问题导致安装失败。在<code>Centos7</code>和<code>Ubuntu16.04</code>两种操作系统上，经过测试阿里云源表现还是不错的：</p>
<ul>
<li><strong>Centos7系统更换阿里云源</strong>：</li>
</ul>
<figure class="highlight bash"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div></pre></td><td class="code"><pre><div class="line"><span class="comment"># cd /etc/yum.repos.d</span></div><div class="line"><span class="comment"># cp CentOS-Base.repo CentOS-Base.repo.bak //备份原来的源</span></div><div class="line"><span class="comment"># vim CentOS-Base.repo  //打开源的文件，删除原有的源，写入新的源</span></div></pre></td></tr></table></figure>
<p>清空原本<code>CentOS-Base.repo</code>的内容，写入如下的内容：</p>
<figure class="highlight bash"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div><div class="line">9</div><div class="line">10</div><div class="line">11</div><div class="line">12</div><div class="line">13</div><div class="line">14</div><div class="line">15</div><div class="line">16</div><div class="line">17</div><div class="line">18</div><div class="line">19</div><div class="line">20</div><div class="line">21</div><div class="line">22</div><div class="line">23</div><div class="line">24</div><div class="line">25</div><div class="line">26</div><div class="line">27</div><div class="line">28</div><div class="line">29</div><div class="line">30</div><div class="line">31</div><div class="line">32</div><div class="line">33</div><div class="line">34</div><div class="line">35</div><div class="line">36</div><div class="line">37</div><div class="line">38</div><div class="line">39</div><div class="line">40</div><div class="line">41</div><div class="line">42</div><div class="line">43</div><div class="line">44</div><div class="line">45</div><div class="line">46</div><div class="line">47</div><div class="line">48</div><div class="line">49</div><div class="line">50</div><div class="line">51</div><div class="line">52</div><div class="line">53</div><div class="line">54</div><div class="line">55</div><div class="line">56</div><div class="line">57</div><div class="line">58</div><div class="line">59</div><div class="line">60</div><div class="line">61</div><div class="line">62</div><div class="line">63</div><div class="line">64</div><div class="line">65</div><div class="line">66</div><div class="line">67</div><div class="line">68</div><div class="line">69</div><div class="line">70</div></pre></td><td class="code"><pre><div class="line"><span class="comment"># CentOS-Base.repo</span></div><div class="line"><span class="comment">#</span></div><div class="line"><span class="comment"># The mirror system uses the connecting IP address of the client and the</span></div><div class="line"><span class="comment"># update status of each mirror to pick mirrors that are updated to and</span></div><div class="line"><span class="comment"># geographically close to the client.  You should use this for CentOS updates</span></div><div class="line"><span class="comment"># unless you are manually picking other mirrors.</span></div><div class="line"><span class="comment">#</span></div><div class="line"><span class="comment"># If the mirrorlist= does not work for you, as a fall back you can try the </span></div><div class="line"><span class="comment"># remarked out baseurl= line instead.</span></div><div class="line"><span class="comment">#</span></div><div class="line"><span class="comment">#</span></div><div class="line"></div><div class="line">[base]</div><div class="line">name=CentOS-<span class="variable">$releasever</span> - Base - mirrors.aliyun.com</div><div class="line">failovermethod=priority</div><div class="line">baseurl=http://mirrors.aliyun.com/centos/<span class="variable">$releasever</span>/os/<span class="variable">$basearch</span>/</div><div class="line">        http://mirrors.aliyuncs.com/centos/<span class="variable">$releasever</span>/os/<span class="variable">$basearch</span>/</div><div class="line"><span class="comment">#mirrorlist=http://mirrorlist.centos.org/?release=$releasever&amp;arch=$basearch&amp;repo=os</span></div><div class="line">gpgcheck=1</div><div class="line">gpgkey=http://mirrors.aliyun.com/centos/RPM-GPG-KEY-CentOS-7</div><div class="line"></div><div class="line"><span class="comment">#released updates </span></div><div class="line">[updates]</div><div class="line">name=CentOS-<span class="variable">$releasever</span> - Updates - mirrors.aliyun.com</div><div class="line">failovermethod=priority</div><div class="line">baseurl=http://mirrors.aliyun.com/centos/<span class="variable">$releasever</span>/updates/<span class="variable">$basearch</span>/</div><div class="line">        http://mirrors.aliyuncs.com/centos/<span class="variable">$releasever</span>/updates/<span class="variable">$basearch</span>/</div><div class="line"><span class="comment">#mirrorlist=http://mirrorlist.centos.org/?release=$releasever&amp;arch=$basearch&amp;repo=updates</span></div><div class="line">gpgcheck=1</div><div class="line">gpgkey=http://mirrors.aliyun.com/centos/RPM-GPG-KEY-CentOS-7</div><div class="line">[updates]</div><div class="line">name=CentOS-<span class="variable">$releasever</span> - Updates - mirrors.aliyun.com</div><div class="line">failovermethod=priority</div><div class="line">baseurl=http://mirrors.aliyun.com/centos/<span class="variable">$releasever</span>/updates/<span class="variable">$basearch</span>/</div><div class="line">        http://mirrors.aliyuncs.com/centos/<span class="variable">$releasever</span>/updates/<span class="variable">$basearch</span>/</div><div class="line"><span class="comment">#mirrorlist=http://mirrorlist.centos.org/?release=$releasever&amp;arch=$basearch&amp;repo=updates</span></div><div class="line">gpgcheck=1</div><div class="line">gpgkey=http://mirrors.aliyun.com/centos/RPM-GPG-KEY-CentOS-7</div><div class="line"></div><div class="line"><span class="comment">#additional packages that may be useful</span></div><div class="line">[extras]</div><div class="line">name=CentOS-<span class="variable">$releasever</span> - Extras - mirrors.aliyun.com</div><div class="line">failovermethod=priority</div><div class="line">baseurl=http://mirrors.aliyun.com/centos/<span class="variable">$releasever</span>/extras/<span class="variable">$basearch</span>/</div><div class="line">        http://mirrors.aliyuncs.com/centos/<span class="variable">$releasever</span>/extras/<span class="variable">$basearch</span>/</div><div class="line"><span class="comment">#mirrorlist=http://mirrorlist.centos.org/?release=$releasever&amp;arch=$basearch&amp;repo=extras</span></div><div class="line">gpgcheck=1</div><div class="line">gpgkey=http://mirrors.aliyun.com/centos/RPM-GPG-KEY-CentOS-7</div><div class="line"></div><div class="line"><span class="comment">#additional packages that extend functionality of existing packages</span></div><div class="line">[centosplus]</div><div class="line">name=CentOS-<span class="variable">$releasever</span> - Plus - mirrors.aliyun.com</div><div class="line">failovermethod=priority</div><div class="line">baseurl=http://mirrors.aliyun.com/centos/<span class="variable">$releasever</span>/centosplus/<span class="variable">$basearch</span>/</div><div class="line">        http://mirrors.aliyuncs.com/centos/<span class="variable">$releasever</span>/centosplus/<span class="variable">$basearch</span>/</div><div class="line"><span class="comment">#mirrorlist=http://mirrorlist.centos.org/?release=$releasever&amp;arch=$basearch&amp;repo=centosplus</span></div><div class="line">gpgcheck=1</div><div class="line">enabled=0</div><div class="line">gpgkey=http://mirrors.aliyun.com/centos/RPM-GPG-KEY-CentOS-7</div><div class="line"></div><div class="line"><span class="comment">#contrib - packages by Centos Users</span></div><div class="line">[contrib]</div><div class="line">name=CentOS-<span class="variable">$releasever</span> - Contrib - mirrors.aliyun.com</div><div class="line">failovermethod=priority</div><div class="line">baseurl=http://mirrors.aliyun.com/centos/<span class="variable">$releasever</span>/contrib/<span class="variable">$basearch</span>/</div><div class="line">        http://mirrors.aliyuncs.com/centos/<span class="variable">$releasever</span>/contrib/<span class="variable">$basearch</span>/</div><div class="line"><span class="comment">#mirrorlist=http://mirrorlist.centos.org/?release=$releasever&amp;arch=$basearch&amp;repo=contrib</span></div><div class="line">gpgcheck=1</div><div class="line">enabled=0</div><div class="line">gpgkey=http://mirrors.aliyun.com/centos/RPM-GPG-KEY-CentOS-7</div></pre></td></tr></table></figure>
<p>然后执行以下命令，确定阿里云源已经正常工作：</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><div class="line">1</div></pre></td><td class="code"><pre><div class="line"># yum update //升级本系统的软件</div></pre></td></tr></table></figure>
<ul>
<li><strong><code>Ubuntu16.04</code>更换阿里云源</strong>：</li>
</ul>
<figure class="highlight bash"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div></pre></td><td class="code"><pre><div class="line"><span class="comment"># cd /etc/apt/</span></div><div class="line"><span class="comment"># cp sources.list sources.list.bak //备份原有的源</span></div><div class="line"><span class="comment"># vim sources.list //打开源文件，清空原有的源，写入新的源</span></div></pre></td></tr></table></figure>
<p>清空<code>sources.list</code>中的原有内容，写入如下的内容：</p>
<figure class="highlight bash"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div><div class="line">9</div><div class="line">10</div><div class="line">11</div><div class="line">12</div><div class="line">13</div><div class="line">14</div><div class="line">15</div><div class="line">16</div><div class="line">17</div><div class="line">18</div></pre></td><td class="code"><pre><div class="line"><span class="comment"># deb cdrom:[Ubuntu 16.04 LTS _Xenial Xerus_ - Release amd64 (20160420.1)]/ xenial main restricted</span></div><div class="line">deb-src http://archive.ubuntu.com/ubuntu xenial main restricted <span class="comment">#Added by software-properties</span></div><div class="line">deb http://mirrors.aliyun.com/ubuntu/ xenial main restricted</div><div class="line">deb-src http://mirrors.aliyun.com/ubuntu/ xenial main restricted multiverse universe <span class="comment">#Added by software-properties</span></div><div class="line">deb http://mirrors.aliyun.com/ubuntu/ xenial-updates main restricted</div><div class="line">deb-src http://mirrors.aliyun.com/ubuntu/ xenial-updates main restricted multiverse universe <span class="comment">#Added by software-properties</span></div><div class="line">deb http://mirrors.aliyun.com/ubuntu/ xenial universe</div><div class="line">deb http://mirrors.aliyun.com/ubuntu/ xenial-updates universe</div><div class="line">deb http://mirrors.aliyun.com/ubuntu/ xenial multiverse</div><div class="line">deb http://mirrors.aliyun.com/ubuntu/ xenial-updates multiverse</div><div class="line">deb http://mirrors.aliyun.com/ubuntu/ xenial-backports main restricted universe multiverse</div><div class="line">deb-src http://mirrors.aliyun.com/ubuntu/ xenial-backports main restricted universe multiverse <span class="comment">#Added by software-properties</span></div><div class="line">deb http://archive.canonical.com/ubuntu xenial partner</div><div class="line">deb-src http://archive.canonical.com/ubuntu xenial partner</div><div class="line">deb http://mirrors.aliyun.com/ubuntu/ xenial-security main restricted</div><div class="line">deb-src http://mirrors.aliyun.com/ubuntu/ xenial-security main restricted multiverse universe <span class="comment">#Added by software-properties</span></div><div class="line">deb http://mirrors.aliyun.com/ubuntu/ xenial-security universe</div><div class="line">deb http://mirrors.aliyun.com/ubuntu/ xenial-security multiverse</div></pre></td></tr></table></figure>
<p>然后执行以下命令，确定阿里云源已经换源成功：</p>
<figure class="highlight bash"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div></pre></td><td class="code"><pre><div class="line"><span class="comment"># apt-get update</span></div><div class="line"><span class="comment"># apt-get upgrade //升级本系统的软件</span></div></pre></td></tr></table></figure>
<blockquote>
<p>不同版本的操作系统，对应的源的地址不同，此处只写出了<code>centos7</code>和<code>ubuntu16.04</code>的操作系统对应的阿里云源，其他版本系统的请自行网上搜索。</p>
</blockquote>
<p><strong>安装pip过程中可能遇到的问题</strong></p>
<p>在安装<code>pip</code>的过程中，Devstack会从网上先下载一个<code>get-pip.py</code>的文件到<code>devstack/files/</code>文件夹下面，然后执行<code>python get-pip.py</code>运行这段程序来安装<code>pip</code>。所以当这个过程因为网络问题，导致<code>get-pip.py</code>不能够正常下载，导致安装失败的时候，我们可以手动下载<code>get-pip.py</code>文件，然后将其放入<code>devstack/files/</code>文件夹下面。</p>
<blockquote>
<p>除了上面的方法之外，我们也可以手动安装<code>pip</code><br><figure class="highlight plain"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div></pre></td><td class="code"><pre><div class="line">&gt; $ apt-get install python-pip  //安装pip</div><div class="line">&gt; $ pip install --upgrade pip  //升级到最新版本</div><div class="line">&gt;</div></pre></td></tr></table></figure></p>
</blockquote>
<p><strong>pip换源的问题</strong></p>
<p>由于Devstack部署过程中会用<code>pip</code>安装许多的软件包，而默认的<code>pip</code>的源的地址为<code>https://pypi.python.org/simple</code>这个地址在国内网络环境下访问不是很顺畅，时常出现下载包失败的情况，所以建议更换为国内源，此处换成了豆瓣源：</p>
<figure class="highlight bash"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div></pre></td><td class="code"><pre><div class="line">$ sodu mkdir /root/.pip/  //新建一个.pip文件夹</div><div class="line">$ vim /root/.pip/pip.conf //在新建的文件夹下面新建pip.conf文件</div></pre></td></tr></table></figure>
<p>然后在<code>pip.conf</code>文件中写入以下内容：</p>
<figure class="highlight bash"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div></pre></td><td class="code"><pre><div class="line">[global]</div><div class="line">index-url = https://pypi.douban.com/simple</div></pre></td></tr></table></figure>
<p>此时即可换源成功。</p>
<p><strong>pip安装软件包的问题</strong></p>
<p>如果换源后，<code>pip</code>中的某些软件包，仍然会从官方源下载，并且导致下载失败，可以手动停掉当然运行<code>stack.sh</code>脚本，把出错的安装命令复制一遍，手动指定安装源来进行安装，一般能够成功。命令格式为：</p>
<figure class="highlight bash"><table><tr><td class="gutter"><pre><div class="line">1</div></pre></td><td class="code"><pre><div class="line">$ pip install &lt;YOUR_PACKAGES&gt; -i https://pypi.doubanio.com/simple</div></pre></td></tr></table></figure>
<p>这样该软件包就可以从我们指定的源地址进行下载安装。</p>
<blockquote>
<p>再部署过程中很多软件包<code>pip</code>自动安装失败，导致部署过程出错的问题，都可以通过手动指定软件源，手动安装，然后重新跑<code>stack.sh</code>来解决。</p>
</blockquote>
<p>另外，如果安装过程中出现如下错误：</p>
<figure class="highlight bash"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div></pre></td><td class="code"><pre><div class="line">2016-04-10 08:40:55.596 | [ERROR] /home/devstack/<span class="built_in">functions</span>-common:1066 Failed to update apt repos, we’re dead now</div><div class="line">2016-04-10 08:40:56.600 | Error on <span class="built_in">exit</span></div><div class="line">2016-04-10 08:40:56.601 | ./stack.sh: line 488: generate-subunit: <span class="built_in">command</span> not found</div></pre></td></tr></table></figure>
<p>可以通过运行如下三条命令来解决：</p>
<figure class="highlight bash"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div></pre></td><td class="code"><pre><div class="line">sudo apt-get install python-pip</div><div class="line">sudo pip install --upgrade pip</div><div class="line">sudo pip install -U os-testr -i https://pypi.douban.com/simple</div></pre></td></tr></table></figure>
<p><br><br><strong>长时间卡在运行<code>setup.py</code>程序</strong></p>
<p>如果运行过程中，出现长时间卡在这一步的情况，基本可以手动<code>Ctrl-C</code>停掉部署过程，然后向上翻输出的部署过程，找到如下内容：</p>
<figure class="highlight bash"><table><tr><td class="gutter"><pre><div class="line">1</div></pre></td><td class="code"><pre><div class="line">sudo -H http_proxy= https_proxy= no_proxy= PIP_FIND_LINKS= SETUPTOOLS_SYS_PATH_TECHNIQUE=rewrite /usr/<span class="built_in">local</span>/bin/pip2.7 install -c /opt/stack/requirements/upper-constraints.txt -e /opt/stack/keystone</div></pre></td></tr></table></figure>
<p>复制这段文字，然后手动运行这段命令，运行过程中如果出现安装源的问题，就用上面的<code>-i https://pypi.douban.com/simple</code>来制定安装源，如果能正常下载安装，就让它继续安装就可以，另外，此过程中如果出现某一个软件包安装时间过程也可以按一下<code>Crtl-C</code>，会自动重新安装这个软件包。</p>
<p><strong>Python虚拟环境搭建与使用</strong></p>
<figure class="highlight bash"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div></pre></td><td class="code"><pre><div class="line">$ pip install virtualenv <span class="comment">#安装virtualenv工具</span></div><div class="line">$ virtualenv venvName <span class="comment"># 创建名为venvName的虚拟环境</span></div><div class="line">$ <span class="built_in">source</span> venvName/bin/activate <span class="comment"># 进入虚拟环境</span></div></pre></td></tr></table></figure>
<p>在部署过程中，Devstack会搭建好几个虚拟环境，这些虚拟环境都可以用上面的第三条命令来手动进入。</p>
<h3 id="Devstack-多节点部署"><a href="#Devstack-多节点部署" class="headerlink" title="Devstack 多节点部署"></a>Devstack 多节点部署</h3><p>Devstack大部分时候只是用来搭建一个<code>all in one</code>的开发测试环境，并不能够用于生产环境，但是作为一个部署工具，其本身也能够承担起多节点部署的任务。Devstack的多节点部署的本质就是：在不同的节点上，使用不同的<code>local.conf</code>配置文件来运行Devstack的部署脚本。但需要注意的是，Openstack的多节点部署不仅仅意味着不同的项目部署到不同的节点上，我们应该理解为，将Openstack不同的服务部署到不同的节点上，不同节点承担不同的功能。</p>
<p>一般来说，很少有人用Devstack来进行多节点的部署，这里可以只做了解即可。</p>
<p><code>Controller</code>节点的配置文件内容：</p>
<figure class="highlight bash"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div><div class="line">9</div><div class="line">10</div><div class="line">11</div><div class="line">12</div><div class="line">13</div><div class="line">14</div><div class="line">15</div><div class="line">16</div><div class="line">17</div><div class="line">18</div><div class="line">19</div><div class="line">20</div><div class="line">21</div><div class="line">22</div><div class="line">23</div><div class="line">24</div><div class="line">25</div><div class="line">26</div><div class="line">27</div></pre></td><td class="code"><pre><div class="line"><span class="comment"># Misc</span></div><div class="line">ADMIN_PASSWORD=&lt;YOUR_PASSWORD&gt;</div><div class="line">DATABASE_PASSWORD=<span class="variable">$ADMIN_PASSWORD</span></div><div class="line">RABBIT_PASSWORD=<span class="variable">$ADMIN_PASSWORD</span></div><div class="line">SERVICE_PASSWORD=<span class="variable">$ADMIN_PASSWORD</span></div><div class="line">SERVICE_TOKEN=<span class="variable">$ADMIN_PASSWORD</span></div><div class="line"></div><div class="line"><span class="comment"># Target Path</span></div><div class="line">DEST=/opt/stack.mitaka</div><div class="line"></div><div class="line"><span class="comment"># Enable Logging</span></div><div class="line">LOGFILE=<span class="variable">$DEST</span>/logs/stack.sh.log</div><div class="line">VERBOSE=True</div><div class="line">LOG_COLOR=True</div><div class="line">SCREEN_LOGDIR=<span class="variable">$DEST</span>/logs</div><div class="line"></div><div class="line"><span class="comment"># Current host ip</span></div><div class="line">HOST_IP=192.168.56.102</div><div class="line">FLAT_INTERFACE=eth1</div><div class="line"></div><div class="line"><span class="comment"># 这个地方选择 True， 开启多节点部署</span></div><div class="line">MULTI_HOST=True</div><div class="line"></div><div class="line"><span class="comment"># 将应该部署到这个节点上的都 enable，部署到其他节点的都 disable</span></div><div class="line"><span class="comment"># Enable/Disable Nova/Cinder ControllerNode service</span></div><div class="line">enable_service n-novnc n-cauth</div><div class="line">disable_service n-cpu n-net n-api-meta c-vol</div></pre></td></tr></table></figure>
<p><code>computer</code>节点的配置文件内容：</p>
<figure class="highlight bash"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div><div class="line">9</div><div class="line">10</div><div class="line">11</div><div class="line">12</div><div class="line">13</div><div class="line">14</div><div class="line">15</div><div class="line">16</div><div class="line">17</div><div class="line">18</div><div class="line">19</div><div class="line">20</div><div class="line">21</div><div class="line">22</div><div class="line">23</div><div class="line">24</div><div class="line">25</div><div class="line">26</div><div class="line">27</div><div class="line">28</div><div class="line">29</div><div class="line">30</div><div class="line">31</div><div class="line">32</div><div class="line">33</div><div class="line">34</div><div class="line">35</div><div class="line">36</div><div class="line">37</div><div class="line">38</div><div class="line">39</div><div class="line">40</div><div class="line">41</div><div class="line">42</div><div class="line">43</div><div class="line">44</div><div class="line">45</div><div class="line">46</div><div class="line">47</div><div class="line">48</div><div class="line">49</div><div class="line">50</div><div class="line">51</div><div class="line">52</div><div class="line">53</div><div class="line">54</div><div class="line">55</div><div class="line">56</div><div class="line">57</div><div class="line">58</div><div class="line">59</div><div class="line">60</div><div class="line">61</div><div class="line">62</div><div class="line">63</div><div class="line">64</div><div class="line">65</div><div class="line">66</div><div class="line">67</div><div class="line">68</div><div class="line">69</div><div class="line">70</div><div class="line">71</div><div class="line">72</div><div class="line">73</div><div class="line">74</div><div class="line">75</div><div class="line">76</div><div class="line">77</div><div class="line">78</div><div class="line">79</div><div class="line">80</div><div class="line">81</div><div class="line">82</div><div class="line">83</div><div class="line">84</div><div class="line">85</div><div class="line">86</div><div class="line">87</div><div class="line">88</div><div class="line">89</div><div class="line">90</div><div class="line">91</div><div class="line">92</div><div class="line">93</div><div class="line">94</div><div class="line">95</div><div class="line">96</div><div class="line">97</div><div class="line">98</div><div class="line">99</div><div class="line">100</div><div class="line">101</div><div class="line">102</div><div class="line">103</div><div class="line">104</div><div class="line">105</div><div class="line">106</div><div class="line">107</div><div class="line">108</div><div class="line">109</div><div class="line">110</div><div class="line">111</div><div class="line">112</div><div class="line">113</div><div class="line">114</div><div class="line">115</div><div class="line">116</div><div class="line">117</div><div class="line">118</div><div class="line">119</div><div class="line">120</div><div class="line">121</div><div class="line">122</div><div class="line">123</div><div class="line">124</div><div class="line">125</div><div class="line">126</div><div class="line">127</div><div class="line">128</div><div class="line">129</div><div class="line">130</div><div class="line">131</div><div class="line">132</div><div class="line">133</div><div class="line">134</div><div class="line">135</div><div class="line">136</div><div class="line">137</div><div class="line">138</div><div class="line">139</div><div class="line">140</div><div class="line">141</div><div class="line">142</div><div class="line">143</div></pre></td><td class="code"><pre><div class="line"><span class="comment"># Misc</span></div><div class="line">ADMIN_PASSWORD=&lt;YOUR_PASSWORD&gt;</div><div class="line">DATABASE_PASSWORD=<span class="variable">$ADMIN_PASSWORD</span></div><div class="line">RABBIT_PASSWORD=<span class="variable">$ADMIN_PASSWORD</span></div><div class="line">SERVICE_PASSWORD=<span class="variable">$ADMIN_PASSWORD</span></div><div class="line">SERVICE_TOKEN=<span class="variable">$ADMIN_PASSWORD</span></div><div class="line"></div><div class="line"><span class="comment"># Target Path</span></div><div class="line">DEST=/opt/stack.mitaka</div><div class="line"></div><div class="line"><span class="comment"># Enable Logging</span></div><div class="line">LOGFILE=<span class="variable">$DEST</span>/logs/stack.sh.log</div><div class="line">VERBOSE=True</div><div class="line">LOG_COLOR=True</div><div class="line">SCREEN_LOGDIR=<span class="variable">$DEST</span>/logs</div><div class="line"></div><div class="line"><span class="comment"># Current host ip</span></div><div class="line">HOST_IP=192.168.56.103</div><div class="line">FLAT_INTERFACE=eth1</div><div class="line"></div><div class="line"><span class="comment"># Enable Nova/Cinder ComputeNode service</span></div><div class="line">enable_service n-novnc n-cauth</div><div class="line">ENABLED_SERVICES=n-cpu,n-net,n-api-meta,c-vol</div><div class="line"></div><div class="line"><span class="comment"># Needed by cinder-volume service</span></div><div class="line">DATABASE_TYPE=mysql</div><div class="line"></div><div class="line"><span class="comment"># ControllerNode ipaddress</span></div><div class="line">SERVICE_HOST=192.168.56.102</div><div class="line">MYSQL_HOST=<span class="variable">$SERVICE_HOST</span></div><div class="line">RABBIT_HOST=<span class="variable">$SERVICE_HOST</span></div><div class="line">GLANCE_HOSTPORT=<span class="variable">$SERVICE_HOST</span>:9292</div><div class="line">NOVA_VNC_ENABLED=True</div><div class="line">NOVNCPROXY_URL=<span class="string">"http://<span class="variable">$SERVICE_HOST</span>:6080/vnc_auto.html"</span></div><div class="line">VNCSERVER_LISTEN=<span class="variable">$HOST_IP</span></div><div class="line">VNCSERVER_PROXYCLIENT_ADDRESS=<span class="variable">$VNCSERVER_LISTEN</span></div><div class="line"></div><div class="line">```bash</div><div class="line"></div><div class="line"><span class="comment">### 附：本次部署过程中用到的`local.conf`文件</span></div><div class="line"></div><div class="line">本次部署过程中，我们开启了`Sahara`服务，`ceilometer`服务，`aodh`服务和`heat`服务，这几项服务Devstack部署过程中默认是不安装的，需要手动开启，另外还有一些其他的组件也可以在部署过程中开启。具体的方法，可以在Openstack官网相应组件的介绍的`xxx and devstack`页面下找到。</div><div class="line"></div><div class="line">`local.conf`文件内容：</div><div class="line"></div><div class="line">```bash</div><div class="line">[[<span class="built_in">local</span>|localrc]]</div><div class="line"><span class="comment">############################################################</span></div><div class="line"><span class="comment"># Customize the following HOST_IP based on your installation</span></div><div class="line"><span class="comment">############################################################</span></div><div class="line">HOST_IP=10.10.87.5</div><div class="line"><span class="comment">#NEUTRON_CREATE_INITIAL_NETWORKS=False</span></div><div class="line">GIT_BASE=http://git.trystack.cn</div><div class="line">NOVNC_REPO=http://git.trystack.cn/kanaka/noVNC.git</div><div class="line">SPICE_REPO=http://git.trystack.cn/git/spice/spice-html5.git</div><div class="line">SERVICE_PASSWORD=123</div><div class="line">ADMIN_PASSWORD=123</div><div class="line">SERVICE_TOKEN=123</div><div class="line">IP_VERSION=4</div><div class="line">DATABASE_PASSWORD=123</div><div class="line">RABBIT_PASSWORD=123</div><div class="line"></div><div class="line"><span class="comment">############################################################</span></div><div class="line"><span class="comment"># Customize the following section based on your installation</span></div><div class="line"><span class="comment">############################################################</span></div><div class="line"></div><div class="line"><span class="comment"># Pip</span></div><div class="line"><span class="comment">#PIP_USE_MIRRORS=False</span></div><div class="line"><span class="comment">#USE_GET_PIP=1</span></div><div class="line"></div><div class="line"><span class="comment">#OFFLINE=False</span></div><div class="line"><span class="comment">#RECLONE=True</span></div><div class="line"><span class="comment">#ENABLE_IDENTITY_V2=False</span></div><div class="line"></div><div class="line"><span class="comment"># Logging</span></div><div class="line">LOGFILE=<span class="variable">$DEST</span>/logs/stack.sh.log</div><div class="line">SCREEN_LOGDIR=<span class="variable">$DEST</span>/logs/screen</div><div class="line">VERBOSE=True</div><div class="line">ENABLE_DEBUG_LOG_LEVEL=True</div><div class="line">ENABLE_VERBOSE_LOG_LEVEL=True</div><div class="line"></div><div class="line"><span class="comment"># Neutron ML2 with OpenVSwitch</span></div><div class="line"></div><div class="line"><span class="comment">#Q_PLUGIN=ml2</span></div><div class="line"><span class="comment">#Q_AGENT=openvswitch</span></div><div class="line"></div><div class="line"><span class="comment">#Q_DVR_MODE=dvr_snat</span></div><div class="line"></div><div class="line"><span class="comment">#enable_plugin gbp http://git.trystack.cn/openstack/group-based-policy master</span></div><div class="line"><span class="comment">#enable_service neutron</span></div><div class="line"><span class="comment">#enable_service q-svc</span></div><div class="line"><span class="comment">#enable_service q-agt</span></div><div class="line"><span class="comment">#enable_service q-meta</span></div><div class="line"><span class="comment">#enable_service q-dhcp</span></div><div class="line"><span class="comment">#enable_service q-l3</span></div><div class="line"><span class="comment">#disable_service n-net</span></div><div class="line"><span class="comment">#disable_service c-api cinder c-bak c-vol c-sch</span></div><div class="line"><span class="comment">#disable_service tempest</span></div><div class="line"><span class="comment">#disable_service heat h-api h-eng</span></div><div class="line"></div><div class="line"><span class="comment"># Swift</span></div><div class="line"><span class="comment"># -----</span></div><div class="line"></div><div class="line"><span class="comment"># Swift is now used as the back-end for the S3-like object store. Setting the</span></div><div class="line"><span class="comment"># hash value is required and you will be prompted for it if Swift is enabled</span></div><div class="line"><span class="comment"># so just set it to something already:</span></div><div class="line">SWIFT_HASH=66a3d6b56c1f479c8b4e70ab5c2000f5</div><div class="line"></div><div class="line"><span class="comment"># For development purposes the default of 3 replicas is usually not required.</span></div><div class="line"><span class="comment"># Set this to 1 to save some resources:</span></div><div class="line">SWIFT_REPLICAS=1</div><div class="line"></div><div class="line"><span class="comment"># The data for Swift is stored by default in (``$DEST/data/swift``),</span></div><div class="line"><span class="comment"># or (``$DATA_DIR/swift``) if ``DATA_DIR`` has been set, and can be</span></div><div class="line"><span class="comment"># moved by setting ``SWIFT_DATA_DIR``. The directory will be created</span></div><div class="line"><span class="comment"># if it does not exist.</span></div><div class="line">SWIFT_DATA_DIR=<span class="variable">$DEST</span>/data</div><div class="line"></div><div class="line"><span class="comment"># Enable sahara</span></div><div class="line">enable_plugin sahara http://git.trystack.cn/openstack/sahara</div><div class="line"></div><div class="line"><span class="comment"># Enable sahara-dashboard</span></div><div class="line">enable_plugin sahara-dashboard http://git.trystack.cn/openstack/sahara-dashboard</div><div class="line"></div><div class="line"><span class="comment">#Enable heat services</span></div><div class="line">enable_service h-eng h-api h-api-cfn h-api-cw</div><div class="line"></div><div class="line"><span class="comment">#Enable heat plugin</span></div><div class="line">enable_plugin heat http://git.trystack.cn/openstack/heat</div><div class="line"></div><div class="line">IMAGE_URL_SITE=<span class="string">"http://download.fedoraproject.org"</span></div><div class="line">IMAGE_URL_PATH=<span class="string">"/pub/fedora/linux/releases/25/CloudImages/x86_64/images/"</span></div><div class="line">IMAGE_URL_FILE=<span class="string">"Fedora-Cloud-Base-25-1.3.x86_64.qcow2"</span></div><div class="line">IMAGE_URLS+=<span class="string">","</span><span class="variable">$IMAGE_URL_SITE</span><span class="variable">$IMAGE_URL_PATH</span><span class="variable">$IMAGE_URL_FILE</span></div><div class="line"></div><div class="line"></div><div class="line"><span class="comment">#Enable ceilometer and aodh service</span></div><div class="line">CEILOMETER_BACKEND=mongodb</div><div class="line">enable_plugin ceilometer http://git.trystack.cn/openstack/ceilometer</div><div class="line">enable_plugin aodh http://git.trystack.cn/openstack/aodh</div><div class="line"></div><div class="line"><span class="comment">#Enable OSprofiler service</span></div><div class="line">CEILOMETER_NOTIFICATION_TOPICS=notifications,profiler</div></pre></td></tr></table></figure>
<h3 id="Reference"><a href="#Reference" class="headerlink" title="Reference"></a>Reference</h3><ul>
<li><a href="https://docs.openstack.org/developer/devstack/" target="_blank" rel="external">Devstack官网</a></li>
<li><a href="https://docs.openstack.org/developer/devstack/configuration.html" target="_blank" rel="external">Devstack配置文件详解</a></li>
<li><a href="http://lib.csdn.net/article/openstack/58949" target="_blank" rel="external">Openstack 实现技术分解 (1) 开发环境 — Devstack 部署案例详解</a></li>
<li><a href="http://blog.csdn.net/xjtuse_mal/article/details/7669371" target="_blank" rel="external"> Openstack 开发人员安装脚本解读</a></li>
<li><a href="http://blog.sina.com.cn/s/blog_7643a1bf0102vhga.html" target="_blank" rel="external">DevStack剖析 （二）DevStack配置过程简述</a></li>
<li><a href="http://www.chenshake.com/openstack-deployment-tool-summary/" target="_blank" rel="external">Openstack部署工具总结——陈沙克日志</a></li>
<li><a href="http://www.chenshake.com/devstack-installation-and-testing/" target="_blank" rel="external">devstack安装和测试——陈沙克日志</a></li>
<li>国内的Openstack的git库: <a href="http://git.trystack.cn/cgit" target="_blank" rel="external">http://git.trystack.cn/cgit</a></li>
</ul>
<blockquote>
<ul>
<li>以上只是个人使用Devstack的一个学习过程的总结，其中难免有疏漏或者不当的地方，敬请指出！</li>
<li>文中部分内容来源于网络，在此对于原作者表示感谢！</li>
</ul>
</blockquote>

      
    </div>

    <div>
      
        

      
    </div>

    <div>
      
        
  <div style="padding: 10px 0; margin: 20px auto; width: 90%; text-align: center;">
    <div></div>
    <button id="rewardButton" disable="enable" onclick="var qr = document.getElementById('QR'); if (qr.style.display === 'none') {qr.style.display='block';} else {qr.style.display='none'}">
      <span>赏</span>
    </button>
    <div id="QR" style="display: none;">
      
        <div id="wechat" style="display: inline-block">
          <img id="wechat_qr" src="/images/jok.png" alt="小马 WeChat Pay"/>
          <p>微信打赏</p>
        </div>
      
      
    </div>
  </div>


      
    </div>

    <div>
      
        

      
    </div>

    <footer class="post-footer">
      
        <div class="post-tags">
          
            <a href="/tags/Devstack/" rel="tag"># Devstack</a>
          
            <a href="/tags/Openstack/" rel="tag"># Openstack</a>
          
            <a href="/tags/开发环境/" rel="tag"># 开发环境</a>
          
        </div>
      

      
        
      

      
        <div class="post-nav">
          <div class="post-nav-next post-nav-item">
            
              <a href="/2016/12/10/数据库和数据仓库的区别/" rel="next" title="数据库和数据仓库的区别">
                <i class="fa fa-chevron-left"></i> 数据库和数据仓库的区别
              </a>
            
          </div>

          <span class="post-nav-divider"></span>

          <div class="post-nav-prev post-nav-item">
            
              <a href="/2017/04/10/Kolla部署工具简介/" rel="prev" title="Kolla部署工具简介">
                Kolla部署工具简介 <i class="fa fa-chevron-right"></i>
              </a>
            
          </div>
        </div>
      

      
      
    </footer>
  </article>



    <div class="post-spread">
      
    </div>
  </div>


          </div>
          


          
  <div class="comments" id="comments">
    
      <div id="cloud-tie-wrapper" class="cloud-tie-wrapper"></div>
    
  </div>


        </div>
        
          
  
  <div class="sidebar-toggle">
    <div class="sidebar-toggle-line-wrap">
      <span class="sidebar-toggle-line sidebar-toggle-line-first"></span>
      <span class="sidebar-toggle-line sidebar-toggle-line-middle"></span>
      <span class="sidebar-toggle-line sidebar-toggle-line-last"></span>
    </div>
  </div>

  <aside id="sidebar" class="sidebar">
    <div class="sidebar-inner">

      

      
        <ul class="sidebar-nav motion-element">
          <li class="sidebar-nav-toc sidebar-nav-active" data-target="post-toc-wrap" >
            文章目录
          </li>
          <li class="sidebar-nav-overview" data-target="site-overview">
            站点概览
          </li>
        </ul>
      

      <section class="site-overview sidebar-panel">
        <div class="site-author motion-element" itemprop="author" itemscope itemtype="http://schema.org/Person">
          <img class="site-author-image" itemprop="image"
               src="/images/avatar1.jpg"
               alt="小马" />
          <p class="site-author-name" itemprop="name">小马</p>
           
              <p class="site-description motion-element" itemprop="description">假装不正经</p>
          
        </div>
        <nav class="site-state motion-element">

          
            <div class="site-state-item site-state-posts">
              <a href="/">
                <span class="site-state-item-count">11</span>
                <span class="site-state-item-name">日志</span>
              </a>
            </div>
          

          
            
            
            <div class="site-state-item site-state-categories">
              <a href="/categories/index.html">
                <span class="site-state-item-count">2</span>
                <span class="site-state-item-name">分类</span>
              </a>
            </div>
          

          
            
            
            <div class="site-state-item site-state-tags">
              <a href="/tags/index.html">
                <span class="site-state-item-count">21</span>
                <span class="site-state-item-name">标签</span>
              </a>
            </div>
          

        </nav>

        
          <div class="feed-link motion-element">
            <a href="/atom.xml" rel="alternate">
              <i class="fa fa-rss"></i>
              RSS
            </a>
          </div>
        

        <div class="links-of-author motion-element">
          
            
              <span class="links-of-author-item">
                <a href="https://github.com/hanbert" target="_blank" title="GitHub">
                  
                    <i class="fa fa-fw fa-github"></i>
                  
                  GitHub
                </a>
              </span>
            
              <span class="links-of-author-item">
                <a href="http://weibo.com/BertHan" target="_blank" title="微博">
                  
                    <i class="fa fa-fw fa-globe"></i>
                  
                  微博
                </a>
              </span>
            
          
        </div>

        
        

        
        

        


      </section>

      
      <!--noindex-->
        <section class="post-toc-wrap motion-element sidebar-panel sidebar-panel-active">
          <div class="post-toc">

            
              
            

            
              <div class="post-toc-content"><ol class="nav"><li class="nav-item nav-level-3"><a class="nav-link" href="#支持的服务"><span class="nav-number">1.</span> <span class="nav-text">支持的服务</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#Devstack-的安装与使用"><span class="nav-number">2.</span> <span class="nav-text">Devstack 的安装与使用</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#Devstack的配置过程"><span class="nav-number">3.</span> <span class="nav-text">Devstack的配置过程</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#Devstack的部署流程及需要注意的问题"><span class="nav-number">4.</span> <span class="nav-text">Devstack的部署流程及需要注意的问题</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#Devstack-多节点部署"><span class="nav-number">5.</span> <span class="nav-text">Devstack 多节点部署</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#Reference"><span class="nav-number">6.</span> <span class="nav-text">Reference</span></a></li></ol></div>
            

          </div>
        </section>
      <!--/noindex-->
      

      

    </div>
  </aside>


        
      </div>
    </main>

    <footer id="footer" class="footer">
      <div class="footer-inner">
        <div class="copyright" >
  
  &copy;  2016 - 
  <span itemprop="copyrightYear">2017</span>
  <span class="with-love">
    <i class="fa fa-heart"></i>
  </span>
  <span class="author" itemprop="copyrightHolder">小马</span>
</div>


<div class="powered-by">
   <a class="theme-link" href="https://www.hanbert.cn"> </a> 小马专属
</div>

<div class="theme-info">
  博客 -
  <a class="theme-link" href="https://www.hanbert.cn">
    记录我的生活
  </a>
</div>


        

        
      </div>
    </footer>

    
      <div class="back-to-top">
        <i class="fa fa-arrow-up"></i>
        
      </div>
    

  </div>

  

<script type="text/javascript">
  if (Object.prototype.toString.call(window.Promise) !== '[object Function]') {
    window.Promise = null;
  }
</script>









  







  
  <script type="text/javascript" src="/lib/jquery/index.js?v=2.1.3"></script>

  
  <script type="text/javascript" src="/lib/fastclick/lib/fastclick.min.js?v=1.0.6"></script>

  
  <script type="text/javascript" src="/lib/jquery_lazyload/jquery.lazyload.js?v=1.9.7"></script>

  
  <script type="text/javascript" src="/lib/velocity/velocity.min.js?v=1.2.1"></script>

  
  <script type="text/javascript" src="/lib/velocity/velocity.ui.min.js?v=1.2.1"></script>

  
  <script type="text/javascript" src="/lib/fancybox/source/jquery.fancybox.pack.js?v=2.1.5"></script>


  


  <script type="text/javascript" src="/js/src/utils.js?v=5.1.0"></script>

  <script type="text/javascript" src="/js/src/motion.js?v=5.1.0"></script>



  
  

  
  <script type="text/javascript" src="/js/src/scrollspy.js?v=5.1.0"></script>
<script type="text/javascript" src="/js/src/post-details.js?v=5.1.0"></script>



  


  <script type="text/javascript" src="/js/src/bootstrap.js?v=5.1.0"></script>



  


  




	





  
    
    <script>
      var cloudTieConfig = {
        url: document.location.href, 
        sourceId: "",
        productKey: "a112af18c95445c591096a909c4fb62c",
        target: "cloud-tie-wrapper"
      };
    </script>
    <script src="https://img1.ws.126.net/f2e/tie/yun/sdk/loader.js"></script>
  










  

  <script type="text/javascript">
    // Popup Window;
    var isfetched = false;
    // Search DB path;
    var search_path = "search.xml";
    if (search_path.length == 0) {
      search_path = "search.xml";
    }
    var path = "/" + search_path;
    // monitor main search box;

    function proceedsearch() {
      $("body")
        .append('<div class="search-popup-overlay local-search-pop-overlay"></div>')
        .css('overflow', 'hidden');
      $('.popup').toggle();
    }
    // search function;
    var searchFunc = function(path, search_id, content_id) {
      'use strict';
      $.ajax({
        url: path,
        dataType: "xml",
        async: true,
        success: function( xmlResponse ) {
          // get the contents from search data
          isfetched = true;
          $('.popup').detach().appendTo('.header-inner');
          var datas = $( "entry", xmlResponse ).map(function() {
            return {
              title: $( "title", this ).text(),
              content: $("content",this).text(),
              url: $( "url" , this).text()
            };
          }).get();
          var $input = document.getElementById(search_id);
          var $resultContent = document.getElementById(content_id);
          $input.addEventListener('input', function(){
            var matchcounts = 0;
            var str='<ul class=\"search-result-list\">';
            var keywords = this.value.trim().toLowerCase().split(/[\s\-]+/);
            $resultContent.innerHTML = "";
            if (this.value.trim().length > 1) {
              // perform local searching
              datas.forEach(function(data) {
                var isMatch = false;
                var content_index = [];
                var data_title = data.title.trim().toLowerCase();
                var data_content = data.content.trim().replace(/<[^>]+>/g,"").toLowerCase();
                var data_url = decodeURIComponent(data.url);
                var index_title = -1;
                var index_content = -1;
                var first_occur = -1;
                // only match artiles with not empty titles and contents
                if(data_title != '') {
                  keywords.forEach(function(keyword, i) {
                    index_title = data_title.indexOf(keyword);
                    index_content = data_content.indexOf(keyword);
                    if( index_title >= 0 || index_content >= 0 ){
                      isMatch = true;
                      if (i == 0) {
                        first_occur = index_content;
                      }
                    }

                  });
                }
                // show search results
                if (isMatch) {
                  matchcounts += 1;
                  str += "<li><a href='"+ data_url +"' class='search-result-title'>"+ data_title +"</a>";
                  var content = data.content.trim().replace(/<[^>]+>/g,"");
                  if (first_occur >= 0) {
                    // cut out 100 characters
                    var start = first_occur - 20;
                    var end = first_occur + 80;
                    if(start < 0){
                      start = 0;
                    }
                    if(start == 0){
                      end = 50;
                    }
                    if(end > content.length){
                      end = content.length;
                    }
                    var match_content = content.substring(start, end);
                    // highlight all keywords
                    keywords.forEach(function(keyword){
                      var regS = new RegExp(keyword, "gi");
                      match_content = match_content.replace(regS, "<b class=\"search-keyword\">"+keyword+"</b>");
                    });

                    str += "<p class=\"search-result\">" + match_content +"...</p>"
                  }
                  str += "</li>";
                }
              })};
            str += "</ul>";
            if (matchcounts == 0) { str = '<div id="no-result"><i class="fa fa-frown-o fa-5x" /></div>' }
            if (keywords == "") { str = '<div id="no-result"><i class="fa fa-search fa-5x" /></div>' }
            $resultContent.innerHTML = str;
          });
          proceedsearch();
        }
      });}

    // handle and trigger popup window;
    $('.popup-trigger').click(function(e) {
      e.stopPropagation();
      if (isfetched == false) {
        searchFunc(path, 'local-search-input', 'local-search-result');
      } else {
        proceedsearch();
      };
    });

    $('.popup-btn-close').click(function(e){
      $('.popup').hide();
      $(".local-search-pop-overlay").remove();
      $('body').css('overflow', '');
    });
    $('.popup').click(function(e){
      e.stopPropagation();
    });
  </script>





  

  
  <script src="https://cdn1.lncld.net/static/js/av-core-mini-0.6.1.js"></script>
  <script>AV.initialize("PON7x61Hu1UYOgywYUN55ig8-gzGzoHsz", "1bzugjkBEuXCThr7Cro7lz6l");</script>
  <script>
    function showTime(Counter) {
      var query = new AV.Query(Counter);
      var entries = [];
      var $visitors = $(".leancloud_visitors");

      $visitors.each(function () {
        entries.push( $(this).attr("id").trim() );
      });

      query.containedIn('url', entries);
      query.find()
        .done(function (results) {
          var COUNT_CONTAINER_REF = '.leancloud-visitors-count';

          if (results.length === 0) {
            $visitors.find(COUNT_CONTAINER_REF).text(0);
            return;
          }

          for (var i = 0; i < results.length; i++) {
            var item = results[i];
            var url = item.get('url');
            var time = item.get('time');
            var element = document.getElementById(url);

            $(element).find(COUNT_CONTAINER_REF).text(time);
          }
          for(var i = 0; i < entries.length; i++) {
            var url = entries[i];
            var element = document.getElementById(url);
            var countSpan = $(element).find(COUNT_CONTAINER_REF);
            if( countSpan.text() == '') {
              countSpan.text(0);
            }
          }
        })
        .fail(function (object, error) {
          console.log("Error: " + error.code + " " + error.message);
        });
    }

    function addCount(Counter) {
      var $visitors = $(".leancloud_visitors");
      var url = $visitors.attr('id').trim();
      var title = $visitors.attr('data-flag-title').trim();
      var query = new AV.Query(Counter);

      query.equalTo("url", url);
      query.find({
        success: function(results) {
          if (results.length > 0) {
            var counter = results[0];
            counter.fetchWhenSave(true);
            counter.increment("time");
            counter.save(null, {
              success: function(counter) {
                var $element = $(document.getElementById(url));
                $element.find('.leancloud-visitors-count').text(counter.get('time'));
              },
              error: function(counter, error) {
                console.log('Failed to save Visitor num, with error message: ' + error.message);
              }
            });
          } else {
            var newcounter = new Counter();
            /* Set ACL */
            var acl = new AV.ACL();
            acl.setPublicReadAccess(true);
            acl.setPublicWriteAccess(true);
            newcounter.setACL(acl);
            /* End Set ACL */
            newcounter.set("title", title);
            newcounter.set("url", url);
            newcounter.set("time", 1);
            newcounter.save(null, {
              success: function(newcounter) {
                var $element = $(document.getElementById(url));
                $element.find('.leancloud-visitors-count').text(newcounter.get('time'));
              },
              error: function(newcounter, error) {
                console.log('Failed to create');
              }
            });
          }
        },
        error: function(error) {
          console.log('Error:' + error.code + " " + error.message);
        }
      });
    }

    $(function() {
      var Counter = AV.Object.extend("Counter");
      if ($('.leancloud_visitors').length == 1) {
        addCount(Counter);
      } else if ($('.post-title-link').length > 1) {
        showTime(Counter);
      }
    });
  </script>



  

  
  
    <script type="text/x-mathjax-config">
      MathJax.Hub.Config({
        tex2jax: {
          inlineMath: [ ['$','$'], ["\\(","\\)"]  ],
          processEscapes: true,
          skipTags: ['script', 'noscript', 'style', 'textarea', 'pre', 'code']
        }
      });
    </script>

    <script type="text/x-mathjax-config">
      MathJax.Hub.Queue(function() {
        var all = MathJax.Hub.getAllJax(), i;
        for (i=0; i < all.length; i += 1) {
          all[i].SourceElement().parentNode.className += ' has-jax';
        }
      });
    </script>
    <script type="text/javascript" src="//cdn.mathjax.org/mathjax/latest/MathJax.js?config=TeX-AMS-MML_HTMLorMML"></script>
  


  

  
  <!-- 背景动画 -->
  <div id="particles-js"></div>
  <script type="text/javascript" src="/js/src/particle.js"></script>
  <!-- <script src="js/app.js"></script> -->
  
</body>
</html>
